
#ifndef __NODE_HPP__
#define __NODE_HPP__
#include "macro.hpp"
#include <vector>
#include <cassert>
#include "subject.hpp"
#include "component.hpp"

#include <memory>
#include <string>
namespace footman {
    class Node : public Object, public Subject {
        static uint32_t __EntityIdCounter;
    protected:
        ComponentArray _components;
        ComponentBitSet _componentBitSet;
    public:
        uint32_t entityId = 0;
        mb active = 1;
        Node();
        virtual ~Node();

        template <class... T>
        bool hasComponent() {
            return Component::BoolListAnd( _componentBitSet[Component::__GetComponentTypeID<T>()]... );
        }
        template <class T>
        T & addComponent()
        {
            auto com = Component::Create<T>( this );
            ComponentID typeId = Component::__GetComponentTypeID<T>();
            _components[typeId] = com;
            _componentBitSet[typeId] = true;
            return *com;
        }
        template <class T>
        T& getComponent()
        {
            auto ptr( _components[Component::__GetComponentTypeID<T>()] );
            return *static_cast<T*>( ptr );
        }
        template <class T>
        bool removeComponent() {
            ComponentID typeId = Component::__GetComponentTypeID<T>();
            if ( !hasComponent<T>( ) ) {
                return 0U;
            }
            _components[typeId] = nullptr;
            _componentBitSet[typeId] = false;
            return 1U;
        }
        operator uint32_t() const {
            return entityId;
        }

        std::vector<Node*> children;
        Node* parent = nullptr;
        void addChild( Node& child );
        void removeChild( Node const& child );

        friend class Component;
        friend class ComponentSprite;
    };

}
#endif __NODE_HPP__